/*
 * Copyright (C) 2009 Tony Gentilcore
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.scoreninja.adapter;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

/**
 * Signs all requests to the score service to prevent unauthorized scores.
 * 
 * @author tonygentilcore@gmail.com (Tony Gentilcore)
 */
final class RequestSigner {
  private static final char[] HEX_CHAR = { '0', '1', '2', '3', '4', '5', '6',
      '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
  private final Mac hmacSha1;

  RequestSigner(String privateKey) {
    this.hmacSha1 = getNewHmacSha1(privateKey);
  }

  /**
   * Computes the sha1 signature for the given text.
   * 
   * @param plainText
   * @return
   */
  String getSignature(String plainText) {
    if (hmacSha1 == null) {
      return "";
    }

    hmacSha1.update(plainText.getBytes());
    byte[] digest = hmacSha1.doFinal();
    char[] hexDigest = new char[40];
    for (int i = 0; i < 20; ++i) {
      int byteValue = 0xFF & digest[i]; // Signed to unsigned. Java, man.
      hexDigest[i * 2] = HEX_CHAR[byteValue >> 4];
      hexDigest[i * 2 + 1] = HEX_CHAR[byteValue & 0xf];
    }
    return new String(hexDigest);
  }

  /**
   * Creates a new Mac object for the given private key. May return null.
   * 
   * @param privateKey
   * @return
   */
  private Mac getNewHmacSha1(String privateKey) {
    SecretKey secretKey = new SecretKeySpec(privateKey.getBytes(), "HmacSHA1");
    Mac mac;
    try {
      mac = Mac.getInstance("HmacSHA1");
      try {
        mac.init(secretKey);
      } catch (InvalidKeyException e) {
        return null;
      }
    } catch (NoSuchAlgorithmException e) {
      return null;
    }
    return mac;
  }
}
